package com.boruan.shengtangfeng.core.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.boruan.shengtangfeng.core.dao.IRoleDao;
import com.boruan.shengtangfeng.core.entity.*;
import com.boruan.shengtangfeng.core.entity.RolePermission;
import com.boruan.shengtangfeng.core.entity.SystemUserRole;
import com.boruan.shengtangfeng.core.utils.Consts;
import com.boruan.shengtangfeng.core.utils.GlobalReponse;
import com.boruan.shengtangfeng.core.dao.IPermissionDao;
import com.boruan.shengtangfeng.core.entity.Permission;
import com.boruan.shengtangfeng.core.entity.Role;
import com.boruan.shengtangfeng.core.utils.ZTree;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.boruan.shengtangfeng.core.enums.PermissionLevel;
import com.boruan.shengtangfeng.core.service.IPermissionService;

@Service
public class PermissionService implements IPermissionService {

	@Autowired
	private IPermissionDao permissionDao;
	@Autowired
	private IRoleDao roleDao;
	@Autowired
	private SQLManager sqlManager;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	
	@Override
	public List<ZTree> buildZTree() {
		List<ZTree> result=new ArrayList<ZTree>();
		List<Permission> list=new ArrayList<Permission>();
		list= permissionDao.findByLevel(PermissionLevel.PARENT.getValue());
		ZTree root=new ZTree();
		root.setId("0");
		root.setIsParent(true);
		root.setTitle("allPermission");
		root.setName("所有权限");
		root.setOpen(true);
		root.setChkDisabled(true);
		result.add(root);
		for (Permission permission : list) {
			ZTree zTree=new ZTree();
			zTree.setId(permission.getId()+"");
			zTree.setName(permission.getDisplayName());
			zTree.setIsParent(true);
			zTree.setTitle(permission.getName());
			zTree.setOpen(true);
			zTree.setPId("0");
			result.add(zTree);
			List<Permission> childList=permissionDao.findChildByParentId(permission.getId());
			for(Permission child : childList){
				ZTree zTreeChild=new ZTree();
				zTreeChild.setOpen(false);
				zTreeChild.setIsParent(true);
				zTreeChild.setId(child.getId()+"");
				zTreeChild.setName(child.getDisplayName());
				zTreeChild.setTitle(child.getName());
				zTreeChild.setPId(permission.getId()+"");
				result.add(zTreeChild);
				List<Permission> childList2=permissionDao.findChildByParentId(child.getId());
				for(Permission button : childList2){
					ZTree zTreeButton=new ZTree();
					zTreeButton.setOpen(false);
					zTreeButton.setId(button.getId()+"");
					zTreeButton.setName(button.getDisplayName());
					zTreeButton.setTitle(button.getName());
					zTreeButton.setPId(child.getId()+"");
					result.add(zTreeButton);
				}
			}
		}
		return result;
	}


	@Override
	public void pageQuery(PageQuery<Role> pageData) {
		roleDao.pageQuery(pageData);
	}

	/**
	 * 根据用户创建其菜单树
	 * @param userId
	 * @Author: Cookie
	 */
	@Override
	public List<Permission> buildMenuTree(Long userId) {

		//获取当前角色roleId
		Long roleId = sqlManager.query(SystemUserRole.class).andEq("system_user_id", userId).select().get(0).getRoleId();

		List<Permission> list = (List<Permission>) redisTemplate.opsForValue().get(Consts.ROLE_PERMISSION + roleId);

		if (null != list) {
			return list;
		}

		//构建根节点
		Permission root = new Permission();
		root.setId(0L);

		list = permissionDao.selectMenuList(roleId);
		List<Permission> result = buildTree(list, root);
		//进行缓存
		redisTemplate.opsForValue().set(Consts.ROLE_PERMISSION + roleId, result);

		return result;
	}



	/**
	 * 递归构建树
	 * @param trees
	 * @param permission
	 * @return
	 */
	private List<Permission> buildTree(List<Permission> trees, Permission permission) {

		List<Permission> treeList = new ArrayList<>();

		for (Permission node : trees) {
			if (null == node.getParentId()) {
				continue;
			}
			if (permission.getId().equals(node.getParentId())) {
				node.setSubs(buildTree(trees, node));
				treeList.add(node);
			}
		}
		return treeList;
	}

	/**
	 * 获取当前角色树，是否选中
	 */
	@Override
	public GlobalReponse getRolePermissionTree(Long roleId) {

		List<Permission> treeMenus = (List<Permission>) redisTemplate.opsForValue().get(Consts.ROLE_PERMISSION_ALL);

		if (null == treeMenus) {
			//构建根节点
			Permission root = new Permission();
			root.setId(0L);

			//所有权限
			treeMenus = sqlManager.query(Permission.class).andEq("is_deleted", 0).select();
			treeMenus = buildTree(treeMenus, root);

			//进行缓存
			redisTemplate.opsForValue().set(Consts.ROLE_PERMISSION_ALL, treeMenus);
		}

		//获取当前角色所有权限id，前端设置选中状态
		List<Long> currentRolePermission = sqlManager.query(RolePermission.class).andEq("role_id", roleId).select(Long.class, "permission_id");

		//过滤掉含子节点的id，防止前端加载全选状态
		List<Long> currentRoleParent = new ArrayList<>();
		List<Long> isParentPermission = sqlManager.execute(new SQLReady("select DISTINCT parent_id from permission where parent_id <> 0"), Long.class);
		currentRolePermission.forEach(e -> {
			if (!isParentPermission.contains(e)) {
				currentRoleParent.add(e);
			}
		});

		return GlobalReponse.success().setData(treeMenus).setData1(currentRolePermission).setData2(currentRoleParent);

	}

	@Override
	@Transactional
	public GlobalReponse editRolePermission(Long roleId, List<Long> addPermissions, List<Long> delPermissions) {

		//删除权限
		for (Long permissionId : delPermissions) {
			sqlManager.executeUpdate(new SQLReady("delete from role_permission where role_id = ? and permission_id = ?", roleId, permissionId));
		}

		//增加权限
		List<RolePermission> pos = new ArrayList<>();
		for (Long permissionId : addPermissions) {
			RolePermission po = new RolePermission();
			po.setPermissionId(permissionId);
			po.setRoleId(roleId);
			pos.add(po);
		}
		sqlManager.insertBatch(RolePermission.class, pos);


		//更新redis权限树
		Permission root = new Permission();
		root.setId(0L);
		//进行缓存,一旦出问题，删掉此key，防止前端加载不出菜单
		try {
			List<Permission> list = permissionDao.selectMenuList(roleId);
			List<Permission> result = buildTree(list, root);
			redisTemplate.opsForValue().set(Consts.ROLE_PERMISSION + roleId, result);
		} catch (Exception e) {
			redisTemplate.delete(Consts.ROLE_PERMISSION + roleId);
		}

		return GlobalReponse.success();
	}

}
